package com.ubb.dbms.core.systemCatalog;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

import com.ubb.dbms.core.Utils.SQLExceptions.ItemAlreadyExistsException;
import com.ubb.dbms.core.Utils.SQLExceptions.ItemNotExistsException;
import com.ubb.dbms.domain.xml.Database;
import com.ubb.dbms.domain.xml.Databases;
import com.ubb.dbms.domain.xml.IndexFile;
import com.ubb.dbms.domain.xml.IndexFiles;
import com.ubb.dbms.domain.xml.Table;
import com.ubb.dbms.domain.xml.Tables;

public class SystemCatalogImpl implements SystemCatalog {
	
	public SystemCatalogImpl() {
		File f = new File("catalog.xml");
		if (f.exists()) {
			Databases databases = readFromXml();
			writeInXml(databases);
		}
		else {
			writeInXml(new Databases());
		}
	}

	@Override
	public void createDatabase(Database database) {

		Databases databases = readFromXml();
		List<Database> dbList;
		if (databases.getDatabaseList() != null) {
			dbList = databases.getDatabaseList();
		} else {
			dbList = new ArrayList<Database>();
		}

		dbList.add(database);
		databases.setDatabaseList(dbList);
		writeInXml(databases);
	}

	@Override
	public void createTable(Table table, String usesDatabase)
			throws ItemAlreadyExistsException {
		Databases databases = readFromXml();
		List<Database> dbList = databases.getDatabaseList();
		if (dbList != null) {
			int dbIndex = getUsedDb(dbList, usesDatabase);
			Database db = dbList.get(dbIndex);
			
			Tables tables = db.getTables();
			if (tables == null) {
				tables = new Tables();
			}
			
			List<Table> tableList = tables.getTableList();
			if (tableList == null) {
				tableList = new ArrayList<Table>();
			}
			
			tableList.add(table);
			tables.setTableList(tableList);
			db.setTables(tables);
			dbList.set(dbIndex, db);
			databases.setDatabaseList(dbList);
			writeInXml(databases);
		}

	}
	
	@Override
	public Table getTable(String tableName, String usesDatabase)
			throws ItemNotExistsException {
		Databases databases = readFromXml();
		List<Database> dbList = databases.getDatabaseList();
		if (dbList != null) {
			int dbIndex = getUsedDb(dbList, usesDatabase);
			Database db = dbList.get(dbIndex);
			
			Tables tables = db.getTables();
			if (tables == null) {
				throw new ItemNotExistsException();
			}
			
			List<Table> tableList = tables.getTableList();
			
			final int tableIndex = getUsedTable(tableList, tableName);
			if (tableIndex != -1) {
				return tableList.get(tableIndex);
			}
		}
		throw new ItemNotExistsException();
	}
	
	@Override
	public Database getDatabase(String databaseName) throws ItemNotExistsException {
		Databases databases = readFromXml();
		List<Database> dbList = databases.getDatabaseList();
		if (dbList != null) {
			for (int i=0; i< dbList.size(); i++) {
				if (dbList.get(i).getDatabaseName().equals(databaseName)) {
					return dbList.get(i);
				}
			}
		}
		throw new ItemNotExistsException();
	}

	public void writeInXml(Databases databases) {
		try {
			final Serializer s = new Persister();
			File result = new File("catalog.xml");
			s.write(databases, result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Databases readFromXml() {
		try {
			Serializer serializer = new Persister();
			File source = new File("catalog.xml");
			Databases dbXml;
			dbXml = serializer.read(Databases.class, source);
			return dbXml;
		} catch (Exception e) {
			return null;
		}
	}
	
	public int getUsedDb(List<Database>dbList, String dbName) {
		for (int i=0; i< dbList.size(); i++) {
			if (dbList.get(i).getDatabaseName().equals(dbName)) {
				return i;
			}
		}
		return -1;
	}
	
	public int getUsedTable(List<Table>tableList, String tableName) {
		for (int i=0; i< tableList.size(); i++) {
			if (tableList.get(i).getTableName().equals(tableName)) {
				return i;
			}
		}
		return -1;
	}

	@Override
	public void createIndex(IndexFile indexFile, Table table,
			String usesDatabase) {
		
		IndexFiles indexFiles = table.getIndexFiles();
		if (indexFiles == null) {
			indexFiles = new IndexFiles();
		}
		List<IndexFile> fileList = indexFiles.getIndexFileList();
		if (fileList == null) {
			fileList = new ArrayList<IndexFile>();
		}
		fileList.add(indexFile);
		
		indexFiles.setIndexFileList(fileList);
		table.setIndexFiles(indexFiles);
		
		Databases databases = readFromXml();
		List<Database> dbList = databases.getDatabaseList();
		if (dbList != null) {
			int dbIndex = getUsedDb(dbList, usesDatabase);
			Database db = dbList.get(dbIndex);
			
			Tables tables = db.getTables();
			if (tables == null) {
				tables = new Tables();
			}
			
			List<Table> tableList = tables.getTableList();
			if (tableList == null) {
				tableList = new ArrayList<Table>();
			}
			
			for (int i = 0; i< tableList.size(); i++) {
				if (tableList.get(i).getTableName().equals(table.getTableName())) {
					tableList.set(i, table);
				}
			}
			
			tables.setTableList(tableList);
			db.setTables(tables);
			dbList.set(dbIndex, db);
			databases.setDatabaseList(dbList);
			writeInXml(databases);
		}
		
	}

	@Override
	public void dropDatabase(String databasename) {
		Databases databases = readFromXml();
		if (databases.getDatabaseList() != null) {
			for (Iterator<Database> iterator = databases.getDatabaseList().iterator(); iterator.hasNext();) {
				Database elem = iterator.next();
			    if (elem.getDatabaseName().equals(databasename)) {
			        iterator.remove();
			        break;
			    }
			}
		}
		writeInXml(databases);		
	}
}
